home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / scripts / kconfig / symbol.c < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  19.5 KB  |  974 lines

  1. /*
  2.  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  3.  * Released under the terms of the GNU GPL v2.0.
  4.  */
  5.  
  6. #include <ctype.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <regex.h>
  10. #include <sys/utsname.h>
  11.  
  12. #define LKC_DIRECT_LINK
  13. #include "lkc.h"
  14.  
  15. struct symbol symbol_yes = {
  16.     .name = "y",
  17.     .curr = { "y", yes },
  18.     .flags = SYMBOL_CONST|SYMBOL_VALID,
  19. }, symbol_mod = {
  20.     .name = "m",
  21.     .curr = { "m", mod },
  22.     .flags = SYMBOL_CONST|SYMBOL_VALID,
  23. }, symbol_no = {
  24.     .name = "n",
  25.     .curr = { "n", no },
  26.     .flags = SYMBOL_CONST|SYMBOL_VALID,
  27. }, symbol_empty = {
  28.     .name = "",
  29.     .curr = { "", no },
  30.     .flags = SYMBOL_VALID,
  31. };
  32.  
  33. struct symbol *sym_defconfig_list;
  34. struct symbol *modules_sym;
  35. tristate modules_val;
  36.  
  37. struct expr *sym_env_list;
  38.  
  39. void sym_add_default(struct symbol *sym, const char *def)
  40. {
  41.     struct property *prop = prop_alloc(P_DEFAULT, sym);
  42.  
  43.     prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
  44. }
  45.  
  46. void sym_init(void)
  47. {
  48.     struct symbol *sym;
  49.     struct utsname uts;
  50.     static bool inited = false;
  51.  
  52.     if (inited)
  53.         return;
  54.     inited = true;
  55.  
  56.     uname(&uts);
  57.  
  58.     sym = sym_lookup("UNAME_RELEASE", 0);
  59.     sym->type = S_STRING;
  60.     sym->flags |= SYMBOL_AUTO;
  61.     sym_add_default(sym, uts.release);
  62. }
  63.  
  64. enum symbol_type sym_get_type(struct symbol *sym)
  65. {
  66.     enum symbol_type type = sym->type;
  67.  
  68.     if (type == S_TRISTATE) {
  69.         if (sym_is_choice_value(sym) && sym->visible == yes)
  70.             type = S_BOOLEAN;
  71.         else if (modules_val == no)
  72.             type = S_BOOLEAN;
  73.     }
  74.     return type;
  75. }
  76.  
  77. const char *sym_type_name(enum symbol_type type)
  78. {
  79.     switch (type) {
  80.     case S_BOOLEAN:
  81.         return "boolean";
  82.     case S_TRISTATE:
  83.         return "tristate";
  84.     case S_INT:
  85.         return "integer";
  86.     case S_HEX:
  87.         return "hex";
  88.     case S_STRING:
  89.         return "string";
  90.     case S_UNKNOWN:
  91.         return "unknown";
  92.     case S_OTHER:
  93.         break;
  94.     }
  95.     return "???";
  96. }
  97.  
  98. struct property *sym_get_choice_prop(struct symbol *sym)
  99. {
  100.     struct property *prop;
  101.  
  102.     for_all_choices(sym, prop)
  103.         return prop;
  104.     return NULL;
  105. }
  106.  
  107. struct property *sym_get_env_prop(struct symbol *sym)
  108. {
  109.     struct property *prop;
  110.  
  111.     for_all_properties(sym, prop, P_ENV)
  112.         return prop;
  113.     return NULL;
  114. }
  115.  
  116. struct property *sym_get_default_prop(struct symbol *sym)
  117. {
  118.     struct property *prop;
  119.  
  120.     for_all_defaults(sym, prop) {
  121.         prop->visible.tri = expr_calc_value(prop->visible.expr);
  122.         if (prop->visible.tri != no)
  123.             return prop;
  124.     }
  125.     return NULL;
  126. }
  127.  
  128. struct property *sym_get_range_prop(struct symbol *sym)
  129. {
  130.     struct property *prop;
  131.  
  132.     for_all_properties(sym, prop, P_RANGE) {
  133.         prop->visible.tri = expr_calc_value(prop->visible.expr);
  134.         if (prop->visible.tri != no)
  135.             return prop;
  136.     }
  137.     return NULL;
  138. }
  139.  
  140. static int sym_get_range_val(struct symbol *sym, int base)
  141. {
  142.     sym_calc_value(sym);
  143.     switch (sym->type) {
  144.     case S_INT:
  145.         base = 10;
  146.         break;
  147.     case S_HEX:
  148.         base = 16;
  149.         break;
  150.     default:
  151.         break;
  152.     }
  153.     return strtol(sym->curr.val, NULL, base);
  154. }
  155.  
  156. static void sym_validate_range(struct symbol *sym)
  157. {
  158.     struct property *prop;
  159.     int base, val, val2;
  160.     char str[64];
  161.  
  162.     switch (sym->type) {
  163.     case S_INT:
  164.         base = 10;
  165.         break;
  166.     case S_HEX:
  167.         base = 16;
  168.         break;
  169.     default:
  170.         return;
  171.     }
  172.     prop = sym_get_range_prop(sym);
  173.     if (!prop)
  174.         return;
  175.     val = strtol(sym->curr.val, NULL, base);
  176.     val2 = sym_get_range_val(prop->expr->left.sym, base);
  177.     if (val >= val2) {
  178.         val2 = sym_get_range_val(prop->expr->right.sym, base);
  179.         if (val <= val2)
  180.             return;
  181.     }
  182.     if (sym->type == S_INT)
  183.         sprintf(str, "%d", val2);
  184.     else
  185.         sprintf(str, "0x%x", val2);
  186.     sym->curr.val = strdup(str);
  187. }
  188.  
  189. static void sym_calc_visibility(struct symbol *sym)
  190. {
  191.     struct property *prop;
  192.     tristate tri;
  193.  
  194.     /* any prompt visible? */
  195.     tri = no;
  196.     for_all_prompts(sym, prop) {
  197.         prop->visible.tri = expr_calc_value(prop->visible.expr);
  198.         tri = EXPR_OR(tri, prop->visible.tri);
  199.     }
  200.     if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
  201.         tri = yes;
  202.     if (sym->visible != tri) {
  203.         sym->visible = tri;
  204.         sym_set_changed(sym);
  205.     }
  206.     if (sym_is_choice_value(sym))
  207.         return;
  208.     tri = no;
  209.     if (sym->rev_dep.expr)
  210.         tri = expr_calc_value(sym->rev_dep.expr);
  211.     if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
  212.         tri = yes;
  213.     if (sym->rev_dep.tri != tri) {
  214.         sym->rev_dep.tri = tri;
  215.         sym_set_changed(sym);
  216.     }
  217. }
  218.  
  219. static struct symbol *sym_calc_choice(struct symbol *sym)
  220. {
  221.     struct symbol *def_sym;
  222.     struct property *prop;
  223.     struct expr *e;
  224.  
  225.     /* is the user choice visible? */
  226.     def_sym = sym->def[S_DEF_USER].val;
  227.     if (def_sym) {
  228.         sym_calc_visibility(def_sym);
  229.         if (def_sym->visible != no)
  230.             return def_sym;
  231.     }
  232.  
  233.     /* any of the defaults visible? */
  234.     for_all_defaults(sym, prop) {
  235.         prop->visible.tri = expr_calc_value(prop->visible.expr);
  236.         if (prop->visible.tri == no)
  237.             continue;
  238.         def_sym = prop_get_symbol(prop);
  239.         sym_calc_visibility(def_sym);
  240.         if (def_sym->visible != no)
  241.             return def_sym;
  242.     }
  243.  
  244.     /* just get the first visible value */
  245.     prop = sym_get_choice_prop(sym);
  246.     expr_list_for_each_sym(prop->expr, e, def_sym) {
  247.         sym_calc_visibility(def_sym);
  248.         if (def_sym->visible != no)
  249.             return def_sym;
  250.     }
  251.  
  252.     /* no choice? reset tristate value */
  253.     sym->curr.tri = no;
  254.     return NULL;
  255. }
  256.  
  257. void sym_calc_value(struct symbol *sym)
  258. {
  259.     struct symbol_value newval, oldval;
  260.     struct property *prop;
  261.     struct expr *e;
  262.  
  263.     if (!sym)
  264.         return;
  265.  
  266.     if (sym->flags & SYMBOL_VALID)
  267.         return;
  268.     sym->flags |= SYMBOL_VALID;
  269.  
  270.     oldval = sym->curr;
  271.  
  272.     switch (sym->type) {
  273.     case S_INT:
  274.     case S_HEX:
  275.     case S_STRING:
  276.         newval = symbol_empty.curr;
  277.         break;
  278.     case S_BOOLEAN:
  279.     case S_TRISTATE:
  280.         newval = symbol_no.curr;
  281.         break;
  282.     default:
  283.         sym->curr.val = sym->name;
  284.         sym->curr.tri = no;
  285.         return;
  286.     }
  287.     if (!sym_is_choice_value(sym))
  288.         sym->flags &= ~SYMBOL_WRITE;
  289.  
  290.     sym_calc_visibility(sym);
  291.  
  292.     /* set default if recursively called */
  293.     sym->curr = newval;
  294.  
  295.     switch (sym_get_type(sym)) {
  296.     case S_BOOLEAN:
  297.     case S_TRISTATE:
  298.         if (sym_is_choice_value(sym) && sym->visible == yes) {
  299.             prop = sym_get_choice_prop(sym);
  300.             newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
  301.         } else {
  302.             if (sym->visible != no) {
  303.                 /* if the symbol is visible use the user value
  304.                  * if available, otherwise try the default value
  305.                  */
  306.                 sym->flags |= SYMBOL_WRITE;
  307.                 if (sym_has_value(sym)) {
  308.                     newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
  309.                                   sym->visible);
  310.                     goto calc_newval;
  311.                 }
  312.             }
  313.             if (sym->rev_dep.tri != no)
  314.                 sym->flags |= SYMBOL_WRITE;
  315.             if (!sym_is_choice(sym)) {
  316.                 prop = sym_get_default_prop(sym);
  317.                 if (prop) {
  318.                     sym->flags |= SYMBOL_WRITE;
  319.                     newval.tri = EXPR_AND(expr_calc_value(prop->expr),
  320.                                   prop->visible.tri);
  321.                 }
  322.             }
  323.         calc_newval:
  324.             newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
  325.         }
  326.         if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
  327.             newval.tri = yes;
  328.         break;
  329.     case S_STRING:
  330.     case S_HEX:
  331.     case S_INT:
  332.         if (sym->visible != no) {
  333.             sym->flags |= SYMBOL_WRITE;
  334.             if (sym_has_value(sym)) {
  335.                 newval.val = sym->def[S_DEF_USER].val;
  336.                 break;
  337.             }
  338.         }
  339.         prop = sym_get_default_prop(sym);
  340.         if (prop) {
  341.             struct symbol *ds = prop_get_symbol(prop);
  342.             if (ds) {
  343.                 sym->flags |= SYMBOL_WRITE;
  344.                 sym_calc_value(ds);
  345.                 newval.val = ds->curr.val;
  346.             }
  347.         }
  348.         break;
  349.     default:
  350.         ;
  351.     }
  352.  
  353.     sym->curr = newval;
  354.     if (sym_is_choice(sym) && newval.tri == yes)
  355.         sym->curr.val = sym_calc_choice(sym);
  356.     sym_validate_range(sym);
  357.  
  358.     if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
  359.         sym_set_changed(sym);
  360.         if (modules_sym == sym) {
  361.             sym_set_all_changed();
  362.             modules_val = modules_sym->curr.tri;
  363.         }
  364.     }
  365.  
  366.     if (sym_is_choice(sym)) {
  367.         struct symbol *choice_sym;
  368.         int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
  369.  
  370.         prop = sym_get_choice_prop(sym);
  371.         expr_list_for_each_sym(prop->expr, e, choice_sym) {
  372.             choice_sym->flags |= flags;
  373.             if (flags & SYMBOL_CHANGED)
  374.                 sym_set_changed(choice_sym);
  375.         }
  376.     }
  377.  
  378.     if (sym->flags & SYMBOL_AUTO)
  379.         sym->flags &= ~SYMBOL_WRITE;
  380. }
  381.  
  382. void sym_clear_all_valid(void)
  383. {
  384.     struct symbol *sym;
  385.     int i;
  386.  
  387.     for_all_symbols(i, sym)
  388.         sym->flags &= ~SYMBOL_VALID;
  389.     sym_add_change_count(1);
  390.     if (modules_sym)
  391.         sym_calc_value(modules_sym);
  392. }
  393.  
  394. void sym_set_changed(struct symbol *sym)
  395. {
  396.     struct property *prop;
  397.  
  398.     sym->flags |= SYMBOL_CHANGED;
  399.     for (prop = sym->prop; prop; prop = prop->next) {
  400.         if (prop->menu)
  401.             prop->menu->flags |= MENU_CHANGED;
  402.     }
  403. }
  404.  
  405. void sym_set_all_changed(void)
  406. {
  407.     struct symbol *sym;
  408.     int i;
  409.  
  410.     for_all_symbols(i, sym)
  411.         sym_set_changed(sym);
  412. }
  413.  
  414. bool sym_tristate_within_range(struct symbol *sym, tristate val)
  415. {
  416.     int type = sym_get_type(sym);
  417.  
  418.     if (sym->visible == no)
  419.         return false;
  420.  
  421.     if (type != S_BOOLEAN && type != S_TRISTATE)
  422.         return false;
  423.  
  424.     if (type == S_BOOLEAN && val == mod)
  425.         return false;
  426.     if (sym->visible <= sym->rev_dep.tri)
  427.         return false;
  428.     if (sym_is_choice_value(sym) && sym->visible == yes)
  429.         return val == yes;
  430.     return val >= sym->rev_dep.tri && val <= sym->visible;
  431. }
  432.  
  433. bool sym_set_tristate_value(struct symbol *sym, tristate val)
  434. {
  435.     tristate oldval = sym_get_tristate_value(sym);
  436.  
  437.     if (oldval != val && !sym_tristate_within_range(sym, val))
  438.         return false;
  439.  
  440.     if (!(sym->flags & SYMBOL_DEF_USER)) {
  441.         sym->flags |= SYMBOL_DEF_USER;
  442.         sym_set_changed(sym);
  443.     }
  444.     /*
  445.      * setting a choice value also resets the new flag of the choice
  446.      * symbol and all other choice values.
  447.      */
  448.     if (sym_is_choice_value(sym) && val == yes) {
  449.         struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
  450.         struct property *prop;
  451.         struct expr *e;
  452.  
  453.         cs->def[S_DEF_USER].val = sym;
  454.         cs->flags |= SYMBOL_DEF_USER;
  455.         prop = sym_get_choice_prop(cs);
  456.         for (e = prop->expr; e; e = e->left.expr) {
  457.             if (e->right.sym->visible != no)
  458.                 e->right.sym->flags |= SYMBOL_DEF_USER;
  459.         }
  460.     }
  461.  
  462.     sym->def[S_DEF_USER].tri = val;
  463.     if (oldval != val)
  464.         sym_clear_all_valid();
  465.  
  466.     return true;
  467. }
  468.  
  469. tristate sym_toggle_tristate_value(struct symbol *sym)
  470. {
  471.     tristate oldval, newval;
  472.  
  473.     oldval = newval = sym_get_tristate_value(sym);
  474.     do {
  475.         switch (newval) {
  476.         case no:
  477.             newval = mod;
  478.             break;
  479.         case mod:
  480.             newval = yes;
  481.             break;
  482.         case yes:
  483.             newval = no;
  484.             break;
  485.         }
  486.         if (sym_set_tristate_value(sym, newval))
  487.             break;
  488.     } while (oldval != newval);
  489.     return newval;
  490. }
  491.  
  492. bool sym_string_valid(struct symbol *sym, const char *str)
  493. {
  494.     signed char ch;
  495.  
  496.     switch (sym->type) {
  497.     case S_STRING:
  498.         return true;
  499.     case S_INT:
  500.         ch = *str++;
  501.         if (ch == '-')
  502.             ch = *str++;
  503.         if (!isdigit(ch))
  504.             return false;
  505.         if (ch == '0' && *str != 0)
  506.             return false;
  507.         while ((ch = *str++)) {
  508.             if (!isdigit(ch))
  509.                 return false;
  510.         }
  511.         return true;
  512.     case S_HEX:
  513.         if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
  514.             str += 2;
  515.         ch = *str++;
  516.         do {
  517.             if (!isxdigit(ch))
  518.                 return false;
  519.         } while ((ch = *str++));
  520.         return true;
  521.     case S_BOOLEAN:
  522.     case S_TRISTATE:
  523.         switch (str[0]) {
  524.         case 'y': case 'Y':
  525.         case 'm': case 'M':
  526.         case 'n': case 'N':
  527.             return true;
  528.         }
  529.         return false;
  530.     default:
  531.         return false;
  532.     }
  533. }
  534.  
  535. bool sym_string_within_range(struct symbol *sym, const char *str)
  536. {
  537.     struct property *prop;
  538.     int val;
  539.  
  540.     switch (sym->type) {
  541.     case S_STRING:
  542.         return sym_string_valid(sym, str);
  543.     case S_INT:
  544.         if (!sym_string_valid(sym, str))
  545.             return false;
  546.         prop = sym_get_range_prop(sym);
  547.         if (!prop)
  548.             return true;
  549.         val = strtol(str, NULL, 10);
  550.         return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
  551.                val <= sym_get_range_val(prop->expr->right.sym, 10);
  552.     case S_HEX:
  553.         if (!sym_string_valid(sym, str))
  554.             return false;
  555.         prop = sym_get_range_prop(sym);
  556.         if (!prop)
  557.             return true;
  558.         val = strtol(str, NULL, 16);
  559.         return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
  560.                val <= sym_get_range_val(prop->expr->right.sym, 16);
  561.     case S_BOOLEAN:
  562.     case S_TRISTATE:
  563.         switch (str[0]) {
  564.         case 'y': case 'Y':
  565.             return sym_tristate_within_range(sym, yes);
  566.         case 'm': case 'M':
  567.             return sym_tristate_within_range(sym, mod);
  568.         case 'n': case 'N':
  569.             return sym_tristate_within_range(sym, no);
  570.         }
  571.         return false;
  572.     default:
  573.         return false;
  574.     }
  575. }
  576.  
  577. bool sym_set_string_value(struct symbol *sym, const char *newval)
  578. {
  579.     const char *oldval;
  580.     char *val;
  581.     int size;
  582.  
  583.     switch (sym->type) {
  584.     case S_BOOLEAN:
  585.     case S_TRISTATE:
  586.         switch (newval[0]) {
  587.         case 'y': case 'Y':
  588.             return sym_set_tristate_value(sym, yes);
  589.         case 'm': case 'M':
  590.             return sym_set_tristate_value(sym, mod);
  591.         case 'n': case 'N':
  592.             return sym_set_tristate_value(sym, no);
  593.         }
  594.         return false;
  595.     default:
  596.         ;
  597.     }
  598.  
  599.     if (!sym_string_within_range(sym, newval))
  600.         return false;
  601.  
  602.     if (!(sym->flags & SYMBOL_DEF_USER)) {
  603.         sym->flags |= SYMBOL_DEF_USER;
  604.         sym_set_changed(sym);
  605.     }
  606.  
  607.     oldval = sym->def[S_DEF_USER].val;
  608.     size = strlen(newval) + 1;
  609.     if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
  610.         size += 2;
  611.         sym->def[S_DEF_USER].val = val = malloc(size);
  612.         *val++ = '0';
  613.         *val++ = 'x';
  614.     } else if (!oldval || strcmp(oldval, newval))
  615.         sym->def[S_DEF_USER].val = val = malloc(size);
  616.     else
  617.         return true;
  618.  
  619.     strcpy(val, newval);
  620.     free((void *)oldval);
  621.     sym_clear_all_valid();
  622.  
  623.     return true;
  624. }
  625.  
  626. const char *sym_get_string_value(struct symbol *sym)
  627. {
  628.     tristate val;
  629.  
  630.     switch (sym->type) {
  631.     case S_BOOLEAN:
  632.     case S_TRISTATE:
  633.         val = sym_get_tristate_value(sym);
  634.         switch (val) {
  635.         case no:
  636.             return "n";
  637.         case mod:
  638.             return "m";
  639.         case yes:
  640.             return "y";
  641.         }
  642.         break;
  643.     default:
  644.         ;
  645.     }
  646.     return (const char *)sym->curr.val;
  647. }
  648.  
  649. bool sym_is_changable(struct symbol *sym)
  650. {
  651.     return sym->visible > sym->rev_dep.tri;
  652. }
  653.  
  654. struct symbol *sym_lookup(const char *name, int flags)
  655. {
  656.     struct symbol *symbol;
  657.     const char *ptr;
  658.     char *new_name;
  659.     int hash = 0;
  660.  
  661.     if (name) {
  662.         if (name[0] && !name[1]) {
  663.             switch (name[0]) {
  664.             case 'y': return &symbol_yes;
  665.             case 'm': return &symbol_mod;
  666.             case 'n': return &symbol_no;
  667.             }
  668.         }
  669.         for (ptr = name; *ptr; ptr++)
  670.             hash += *ptr;
  671.         hash &= 0xff;
  672.  
  673.         for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
  674.             if (!strcmp(symbol->name, name) &&
  675.                 (flags ? symbol->flags & flags
  676.                    : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
  677.                 return symbol;
  678.         }
  679.         new_name = strdup(name);
  680.     } else {
  681.         new_name = NULL;
  682.         hash = 256;
  683.     }
  684.  
  685.     symbol = malloc(sizeof(*symbol));
  686.     memset(symbol, 0, sizeof(*symbol));
  687.     symbol->name = new_name;
  688.     symbol->type = S_UNKNOWN;
  689.     symbol->flags |= flags;
  690.  
  691.     symbol->next = symbol_hash[hash];
  692.     symbol_hash[hash] = symbol;
  693.  
  694.     return symbol;
  695. }
  696.  
  697. struct symbol *sym_find(const char *name)
  698. {
  699.     struct symbol *symbol = NULL;
  700.     const char *ptr;
  701.     int hash = 0;
  702.  
  703.     if (!name)
  704.         return NULL;
  705.  
  706.     if (name[0] && !name[1]) {
  707.         switch (name[0]) {
  708.         case 'y': return &symbol_yes;
  709.         case 'm': return &symbol_mod;
  710.         case 'n': return &symbol_no;
  711.         }
  712.     }
  713.     for (ptr = name; *ptr; ptr++)
  714.         hash += *ptr;
  715.     hash &= 0xff;
  716.  
  717.     for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
  718.         if (!strcmp(symbol->name, name) &&
  719.             !(symbol->flags & SYMBOL_CONST))
  720.                 break;
  721.     }
  722.  
  723.     return symbol;
  724. }
  725.  
  726. struct symbol **sym_re_search(const char *pattern)
  727. {
  728.     struct symbol *sym, **sym_arr = NULL;
  729.     int i, cnt, size;
  730.     regex_t re;
  731.  
  732.     cnt = size = 0;
  733.     /* Skip if empty */
  734.     if (strlen(pattern) == 0)
  735.         return NULL;
  736.     if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
  737.         return NULL;
  738.  
  739.     for_all_symbols(i, sym) {
  740.         if (sym->flags & SYMBOL_CONST || !sym->name)
  741.             continue;
  742.         if (regexec(&re, sym->name, 0, NULL, 0))
  743.             continue;
  744.         if (cnt + 1 >= size) {
  745.             void *tmp = sym_arr;
  746.             size += 16;
  747.             sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
  748.             if (!sym_arr) {
  749.                 free(tmp);
  750.                 return NULL;
  751.             }
  752.         }
  753.         sym_arr[cnt++] = sym;
  754.     }
  755.     if (sym_arr)
  756.         sym_arr[cnt] = NULL;
  757.     regfree(&re);
  758.  
  759.     return sym_arr;
  760. }
  761.  
  762.  
  763. static struct symbol *sym_check_expr_deps(struct expr *e)
  764. {
  765.     struct symbol *sym;
  766.  
  767.     if (!e)
  768.         return NULL;
  769.     switch (e->type) {
  770.     case E_OR:
  771.     case E_AND:
  772.         sym = sym_check_expr_deps(e->left.expr);
  773.         if (sym)
  774.             return sym;
  775.         return sym_check_expr_deps(e->right.expr);
  776.     case E_NOT:
  777.         return sym_check_expr_deps(e->left.expr);
  778.     case E_EQUAL:
  779.     case E_UNEQUAL:
  780.         sym = sym_check_deps(e->left.sym);
  781.         if (sym)
  782.             return sym;
  783.         return sym_check_deps(e->right.sym);
  784.     case E_SYMBOL:
  785.         return sym_check_deps(e->left.sym);
  786.     default:
  787.         break;
  788.     }
  789.     printf("Oops! How to check %d?\n", e->type);
  790.     return NULL;
  791. }
  792.  
  793. /* return NULL when dependencies are OK */
  794. static struct symbol *sym_check_sym_deps(struct symbol *sym)
  795. {
  796.     struct symbol *sym2;
  797.     struct property *prop;
  798.  
  799.     sym2 = sym_check_expr_deps(sym->rev_dep.expr);
  800.     if (sym2)
  801.         return sym2;
  802.  
  803.     for (prop = sym->prop; prop; prop = prop->next) {
  804.         if (prop->type == P_CHOICE || prop->type == P_SELECT)
  805.             continue;
  806.         sym2 = sym_check_expr_deps(prop->visible.expr);
  807.         if (sym2)
  808.             break;
  809.         if (prop->type != P_DEFAULT || sym_is_choice(sym))
  810.             continue;
  811.         sym2 = sym_check_expr_deps(prop->expr);
  812.         if (sym2)
  813.             break;
  814.     }
  815.  
  816.     return sym2;
  817. }
  818.  
  819. static struct symbol *sym_check_choice_deps(struct symbol *choice)
  820. {
  821.     struct symbol *sym, *sym2;
  822.     struct property *prop;
  823.     struct expr *e;
  824.  
  825.     prop = sym_get_choice_prop(choice);
  826.     expr_list_for_each_sym(prop->expr, e, sym)
  827.         sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
  828.  
  829.     choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
  830.     sym2 = sym_check_sym_deps(choice);
  831.     choice->flags &= ~SYMBOL_CHECK;
  832.     if (sym2)
  833.         goto out;
  834.  
  835.     expr_list_for_each_sym(prop->expr, e, sym) {
  836.         sym2 = sym_check_sym_deps(sym);
  837.         if (sym2) {
  838.             fprintf(stderr, " -> %s", sym->name);
  839.             break;
  840.         }
  841.     }
  842. out:
  843.     expr_list_for_each_sym(prop->expr, e, sym)
  844.         sym->flags &= ~SYMBOL_CHECK;
  845.  
  846.     if (sym2 && sym_is_choice_value(sym2) &&
  847.         prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
  848.         sym2 = choice;
  849.  
  850.     return sym2;
  851. }
  852.  
  853. struct symbol *sym_check_deps(struct symbol *sym)
  854. {
  855.     struct symbol *sym2;
  856.     struct property *prop;
  857.  
  858.     if (sym->flags & SYMBOL_CHECK) {
  859.         fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
  860.                 sym->prop->file->name, sym->prop->lineno,
  861.             sym->name ? sym->name : "<choice>");
  862.         return sym;
  863.     }
  864.     if (sym->flags & SYMBOL_CHECKED)
  865.         return NULL;
  866.  
  867.     if (sym_is_choice_value(sym)) {
  868.         /* for choice groups start the check with main choice symbol */
  869.         prop = sym_get_choice_prop(sym);
  870.         sym2 = sym_check_deps(prop_get_symbol(prop));
  871.     } else if (sym_is_choice(sym)) {
  872.         sym2 = sym_check_choice_deps(sym);
  873.     } else {
  874.         sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
  875.         sym2 = sym_check_sym_deps(sym);
  876.         sym->flags &= ~SYMBOL_CHECK;
  877.     }
  878.  
  879.     if (sym2) {
  880.         fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
  881.         if (sym2 == sym) {
  882.             fprintf(stderr, "\n");
  883.             zconfnerrs++;
  884.             sym2 = NULL;
  885.         }
  886.     }
  887.  
  888.     return sym2;
  889. }
  890.  
  891. struct property *prop_alloc(enum prop_type type, struct symbol *sym)
  892. {
  893.     struct property *prop;
  894.     struct property **propp;
  895.  
  896.     prop = malloc(sizeof(*prop));
  897.     memset(prop, 0, sizeof(*prop));
  898.     prop->type = type;
  899.     prop->sym = sym;
  900.     prop->file = current_file;
  901.     prop->lineno = zconf_lineno();
  902.  
  903.     /* append property to the prop list of symbol */
  904.     if (sym) {
  905.         for (propp = &sym->prop; *propp; propp = &(*propp)->next)
  906.             ;
  907.         *propp = prop;
  908.     }
  909.  
  910.     return prop;
  911. }
  912.  
  913. struct symbol *prop_get_symbol(struct property *prop)
  914. {
  915.     if (prop->expr && (prop->expr->type == E_SYMBOL ||
  916.                prop->expr->type == E_LIST))
  917.         return prop->expr->left.sym;
  918.     return NULL;
  919. }
  920.  
  921. const char *prop_get_type_name(enum prop_type type)
  922. {
  923.     switch (type) {
  924.     case P_PROMPT:
  925.         return "prompt";
  926.     case P_ENV:
  927.         return "env";
  928.     case P_COMMENT:
  929.         return "comment";
  930.     case P_MENU:
  931.         return "menu";
  932.     case P_DEFAULT:
  933.         return "default";
  934.     case P_CHOICE:
  935.         return "choice";
  936.     case P_SELECT:
  937.         return "select";
  938.     case P_RANGE:
  939.         return "range";
  940.     case P_UNKNOWN:
  941.         break;
  942.     }
  943.     return "unknown";
  944. }
  945.  
  946. void prop_add_env(const char *env)
  947. {
  948.     struct symbol *sym, *sym2;
  949.     struct property *prop;
  950.     char *p;
  951.  
  952.     sym = current_entry->sym;
  953.     sym->flags |= SYMBOL_AUTO;
  954.     for_all_properties(sym, prop, P_ENV) {
  955.         sym2 = prop_get_symbol(prop);
  956.         if (strcmp(sym2->name, env))
  957.             menu_warn(current_entry, "redefining environment symbol from %s",
  958.                   sym2->name);
  959.         return;
  960.     }
  961.  
  962.     prop = prop_alloc(P_ENV, sym);
  963.     prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
  964.  
  965.     sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
  966.     sym_env_list->right.sym = sym;
  967.  
  968.     p = getenv(env);
  969.     if (p)
  970.         sym_add_default(sym, p);
  971.     else
  972.         menu_warn(current_entry, "environment variable %s undefined", env);
  973. }
  974.